`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date: 2024/11/13 12:02:07
// Design Name: 
// Module Name: adc_top
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////


module adc_top(
    input                   sys_clk_i               ,
    input                   sys_rst_n_i             ,   

    input                   adc_offset_detect_req_i ,
    input                   adc_convert_req_i       ,
    output reg              adc_offset_detect_ack_o ,
    output                  adc_convert_ack_o       ,


    output signed[31:0]     Ia_o                    ,
    output signed[31:0]     Ib_o                    ,
    output signed[31:0]     Ic_o                    ,
    output[15:0]            voltage_o               ,
    //adc pin
    output                  ad7928_cs_pin_o         ,
    output                  ad7928_sclk_pin_o       ,
    output                  ad7928_mosi_pin_o       ,
    input                   ad7928_miso_pin_i        
);


reg         adc2IaIbIc_req;
wire        adc2IaIbIc_ack;

reg         ad7928_convert_en;
reg         ad7929_convert_wait;
wire        ad7928_convert_ack;
wire[11:0]  adc_channel_u;
wire[11:0]  adc_channel_v;
wire[11:0]  adc_channel_w;
wire[11:0]  adc_channel_voltage;

reg[31:0]   adc_channel_u_sum;
reg[31:0]   adc_channel_v_sum;
reg[31:0]   adc_channel_w_sum;

reg[15:0]  adc_channel_u_offset;
reg[15:0]  adc_channel_v_offset;
reg[15:0]  adc_channel_w_offset;

reg[15:0]    offset_convert_cnt;


assign adc_convert_ack_o = ( adc2IaIbIc_ack == 1'b1) ? 1'b1 : 1'b0;


always@( posedge sys_clk_i or negedge sys_rst_n_i ) begin
    if( sys_rst_n_i == 1'b0 )
        ad7929_convert_wait <= 1'b0;
    else if( ad7928_convert_ack == 1'b1 )
        ad7929_convert_wait <= 1'b0;
    else if( ad7929_convert_wait == 1'b0 && adc_offset_detect_req_i == 1'b1 )
        ad7929_convert_wait <= 1'b1;
    else
        ad7929_convert_wait <= ad7929_convert_wait;
end

always@( posedge sys_clk_i or negedge sys_rst_n_i ) begin
    if( sys_rst_n_i == 1'b0 )
        ad7928_convert_en <= 1'b0;
    else if( ad7929_convert_wait == 1'b1 )
        ad7928_convert_en <= 1'b0;
    else if( adc_offset_detect_req_i == 1'b1 )
        ad7928_convert_en <= 1'b1;
    else if( adc_convert_req_i == 1'b1 )
        ad7928_convert_en <= 1'b1;
    else
        ad7928_convert_en <= 1'b0;
end

always @( posedge sys_clk_i or negedge sys_rst_n_i ) begin
    if( sys_rst_n_i == 1'b0 )
        adc_offset_detect_ack_o <= 1'b0;
    else if( adc_offset_detect_req_i == 1'b1 && offset_convert_cnt == 'd4095 && ad7928_convert_ack == 1'b1) 
        adc_offset_detect_ack_o <= 1'b1;
    else
        adc_offset_detect_ack_o <= 1'b0;
end

always@( posedge sys_clk_i or negedge sys_rst_n_i ) begin
    if( sys_rst_n_i == 1'b0 )
        offset_convert_cnt <= 'd0;
    else if( adc_offset_detect_req_i == 1'b1 )
        if( ad7928_convert_ack == 1'b1 )
            offset_convert_cnt <= offset_convert_cnt + 1'b1;
        else
            offset_convert_cnt <= offset_convert_cnt;
    else
        offset_convert_cnt <= 'd0;
end

always@( posedge sys_clk_i or negedge sys_rst_n_i ) begin
    if( sys_rst_n_i == 1'b0 ) begin
        adc_channel_u_sum <= 'd0;
        adc_channel_v_sum <= 'd0;
        adc_channel_w_sum <= 'd0;
    end
    else if( adc_offset_detect_req_i == 1'b1  ) begin
        if( ad7928_convert_ack == 1'b1 ) begin
            adc_channel_u_sum <= adc_channel_u_sum + adc_channel_u;
            adc_channel_v_sum <= adc_channel_v_sum + adc_channel_v;
            adc_channel_w_sum <= adc_channel_w_sum + adc_channel_w;
        end
        else begin
            adc_channel_u_sum <= adc_channel_u_sum;
            adc_channel_v_sum <= adc_channel_v_sum;
            adc_channel_w_sum <= adc_channel_w_sum;
        end
    end
    else begin
        adc_channel_u_sum <= 'd0;
        adc_channel_v_sum <= 'd0;
        adc_channel_w_sum <= 'd0;
    end
end


always@( posedge sys_clk_i or negedge sys_rst_n_i ) begin
    if( sys_rst_n_i == 1'b0 ) begin
        adc_channel_u_offset <= 'd1861;
        adc_channel_v_offset <= 'd1861;
        adc_channel_w_offset <= 'd1861;
    end
    else if( adc_offset_detect_ack_o == 1'b1  ) begin
        adc_channel_u_offset <= ( adc_channel_u_sum >> 12 ) - 'd16;
        adc_channel_v_offset <= ( adc_channel_v_sum >> 12 ) - 'd16;
        adc_channel_w_offset <= ( adc_channel_w_sum >> 12 ) - 'd8;
    end
    else begin
        adc_channel_u_offset <= adc_channel_u_offset;
        adc_channel_v_offset <= adc_channel_v_offset;
        adc_channel_w_offset <= adc_channel_w_offset;
    end
end





always@( posedge sys_clk_i or negedge sys_rst_n_i ) begin
    if( sys_rst_n_i == 1'b0 )
        adc2IaIbIc_req <= 1'b0; 
    else if( ad7928_convert_ack == 1'b1 )   
        adc2IaIbIc_req <= 1'b1;
    else
        adc2IaIbIc_req <= 1'b0;
end


adc2IaIbIc adc2IaIbIc_hp(
    .sys_clk_i                  (   sys_clk_i                   ),
    .sys_rst_n_i                (   sys_rst_n_i                 ), 

    .adc2IaIbIc_req_i           (   adc2IaIbIc_req              ),
    .adc2IaIbIc_ack_o           (   adc2IaIbIc_ack              ),

    .adc_channel_u_i            (   adc_channel_u               ),
    .adc_channel_v_i            (   adc_channel_v               ),
    .adc_channel_w_i            (   adc_channel_w               ),

    .adc_channel_u_offset_i     (   adc_channel_u_offset        ),
    .adc_channel_v_offset_i     (   adc_channel_v_offset        ),
    .adc_channel_w_offset_i     (   adc_channel_w_offset        ),
    

    .Ia_o                       (   Ia_o                        ),
    .Ib_o                       (   Ib_o                        ),
    .Ic_o                       (   Ic_o                        )
);



ad7928_driver #(
    .AD7928_CHANNEL_NUM         (   4'd4                        ), // MAX = 8 ��Ҫת����ͨ����
    .AD7928_CHANNEL1_ADDR       (   3'd0                        ), //ͨ��1�ĵ�ַ
    .AD7928_CHANNEL2_ADDR       (   3'd1                        ), //ͨ��2�ĵ�ַ
    .AD7928_CHANNEL3_ADDR       (   3'd2                        ), //ͨ��3�ĵ�ַ
    .AD7928_CHANNEL4_ADDR       (   3'd5                        ), //ͨ��4�ĵ�ַ
    .AD7928_CHANNEL5_ADDR       (   3'd4                        ), //ͨ��5�ĵ�ַ
    .AD7928_CHANNEL6_ADDR       (   3'd5                        ), //ͨ��6�ĵ�ַ
    .AD7928_CHANNEL7_ADDR       (   3'd6                        ), //ͨ��7�ĵ�ַ
    .AD7928_CHANNEL8_ADDR       (   3'd7                        )  //ͨ��8�ĵ�ַ
)ad7928_driver_hp(
    .sys_clk_i                  (   sys_clk_i                   ),
    .sys_rst_n_i                (   sys_rst_n_i                 ),//��λ�͵�ƽ��Ч
    //�û��ӿ�
    .ad7928_convert_en_i        (   ad7928_convert_en           ),//�ߵ�ƽʱ��ʾ����ת��
    .ad7928_convert_ack_o       (   ad7928_convert_ack          ),//ת������ź�
    .ad7928_value0_o            (   adc_channel_u               ),
    .ad7928_value1_o            (   adc_channel_v               ),
    .ad7928_value2_o            (   adc_channel_w               ),
    .ad7928_value3_o            (   adc_channel_voltage         ),
    .ad7928_value4_o            (                               ),
    .ad7928_value5_o            (                               ),
    .ad7928_value6_o            (                               ),
    .ad7928_value7_o            (                               ),
    //�����ӿ�
    .ad7928_cs_pin_o            (   ad7928_cs_pin_o             ),
    .ad7928_sclk_pin_o          (   ad7928_sclk_pin_o           ),
    .ad7928_mosi_pin_o          (   ad7928_mosi_pin_o           ),//оƬ����
    .ad7928_miso_pin_i          (   ad7928_miso_pin_i           ) //оƬ�������
);
endmodule
